/**
 * 客户端测试1006接口脚本（聚合抗性）
 * 依据 test-code-1336.js 流程改造：HTTP登录 → WebSocket连接 → 角色列表 →（无则创建）→ 选择角色 → 调用1006 → 校验数据结构
 */

const http = require('http');
const WebSocket = require('ws');

// 测试配置（保持与现有脚本风格一致）
const CONFIG = {
    server: {
        host: process.env.WS_HOST || 'localhost',
        port: parseInt(process.env.WS_PORT || process.env.HTTP_PORT || '3000', 10),
        protocol: 'http'
    },
    testUser: {
        mobile: process.env.TEST_USER_MOBILE || '17091271111',
        password: process.env.TEST_USER_PASSWORD || '123456',
        passwordHash: process.env.TEST_USER_PASSWORD_HASH || 'e10adc3949ba59abbe56e057f20f883e' // 123456 的md5
    },
    testCharacter: {
        name: '测试角色',
        sex: 1,
        roleType: 1,
        headIndex: 2
    }
};

class Code1006Tester {
    constructor() {
        this.token = null;
        this.userId = null;
        this.ws = null;
        this.characters = [];
        this.selectedCharacter = null;
        this.testResults = [];
        this.resistances = null;
    }

    async runTest() {
        console.log('🛡️ 开始客户端1006接口（聚合抗性）测试...\n');
        try {
            await this.testHttpLogin();
            await this.testWebSocketConnection();
            await this.testQueryCharacters();

            if (this.characters.length === 0) {
                await this.testCreateCharacter();
                await this.testQueryCharacters();
            }

            await this.testSelectCharacter();
            await this.testCode1006GetResistances();
            await this.validateResistances();
            await this.testDisconnect();
            this.printTestResults();
        } catch (error) {
            console.error('❌ 测试过程中发生错误:', error.message);
            this.addTestResult('整体测试', false, error.message);
            // 确保断开连接
            try { await this.testDisconnect(); } catch (_) { }
            process.exit(1);
        }
    }

    async testHttpLogin() {
        console.log('🔐 步骤1: HTTP登录测试...');
        try {
            await this.registerUser();
            const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash
            });

            if (loginData.code === 0 && loginData.data) {
                this.userId = loginData.data.userId;
                this.token = loginData.data.accessToken;
                console.log(`✅ 登录成功: userId=${this.userId}`);
                this.addTestResult('HTTP登录', true, `用户ID: ${this.userId}`);
            } else {
                throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
            }
        } catch (error) {
            console.log('❌ 登录失败:', error.message);
            this.addTestResult('HTTP登录', false, error.message);
            throw error;
        }
    }

    async registerUser() {
        try {
            const res = await this.makeHttpRequest('/user-service/user/register', 'POST', {
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash,
                captcha: '123456'
            });
            console.log('📝 用户注册成功', res);
        } catch (error) {
            if (error.message.includes('MOBILE_EXISTS') || error.message.includes('已存在')) {
                console.log('👤 用户已存在，跳过注册');
            } else {
                console.log('⚠️ 注册失败:', error.message);
            }
        }
    }

    async testWebSocketConnection() {
        console.log('\n🔌 步骤2: WebSocket连接测试...');
        return new Promise((resolve, reject) => {
            try {
                const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
                this.ws = new WebSocket(wsUrl);

                this.ws.on('open', async () => {
                    console.log('✅ WebSocket连接成功');
                    this.addTestResult('WebSocket连接', true, '连接建立成功');
                    this.setupMessageHandler();
                    await this.delay(500);
                    resolve();
                });

                this.ws.on('error', (error) => {
                    console.log('❌ WebSocket连接失败:', error.message);
                    this.addTestResult('WebSocket连接', false, error.message);
                    reject(error);
                });

                this.ws.on('close', () => {
                    console.log('🔌 WebSocket连接已关闭');
                });

                setTimeout(() => {
                    if (this.ws.readyState === WebSocket.CONNECTING) {
                        this.ws.close();
                        reject(new Error('连接超时'));
                    }
                }, 10000);
            } catch (error) {
                reject(error);
            }
        });
    }

    setupMessageHandler() {
        this.ws.on('message', (data) => {
            try {
                const message = JSON.parse(data.toString());
                console.log('📨 收到消息:', JSON.stringify(message, null, 2));
                this.handleWebSocketResponse(message);
            } catch (error) {
                console.error('❌ 消息解析失败:', error.message);
            }
        });
    }

    handleWebSocketResponse(message) {
        const { act_id, code, roleList, roleCount } = message;
        switch (act_id) {
            case 3:
                if (roleList && Array.isArray(roleList)) {
                    this.characters = roleList;
                    console.log(`📋 获取到${roleCount || roleList.length}个角色`);
                }
                break;
            case 4:
                if (code === 0) {
                    console.log('🎯 角色选择成功');
                }
                break;
            case 5:
            case 390:
                if (code === 0) {
                    console.log('🆕 角色创建成功');
                }
                break;
            case 1006:
                if (code === 0) {
                    this.resistances = message.data || null;
                }
                break;
        }
    }

    async testQueryCharacters() {
        console.log('\n📋 步骤3: 查询角色列表...');
        return new Promise(async (resolve) => {
            if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
                this.addTestResult('查询角色列表', false, 'WebSocket未连接');
                resolve();
                return;
            }

            await this.delay(800);
            const handler = (raw) => {
                try {
                    const msg = JSON.parse(raw.toString());
                    if (msg.act_id === 3) {
                        this.ws.removeListener('message', handler);
                        if (msg.roleList && Array.isArray(msg.roleList)) {
                            this.characters = msg.roleList;
                            console.log(`✅ 查询成功，共${msg.roleCount || msg.roleList.length}个角色`);
                            this.addTestResult('查询角色列表', true, `获取${this.characters.length}个角色`);
                        } else {
                            this.characters = [];
                            console.log('✅ 查询成功，暂无角色');
                            this.addTestResult('查询角色列表', true, '获取0个角色');
                        }
                        resolve();
                    }
                } catch (_) { }
            };
            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 3, d: null }));

            setTimeout(() => {
                this.ws.removeListener('message', handler);
                this.addTestResult('查询角色列表', false, '请求超时');
                resolve();
            }, 10000);
        });
    }

    async testCreateCharacter() {
        console.log('\n🆕 步骤4: 创建角色测试...');
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            this.addTestResult('创建角色', false, 'WebSocket未连接');
            return;
        }
        return new Promise((resolve) => {
            let responseReceived = false;
            let retryCount = 0;
            const maxRetries = 2;

            const handler = (raw) => {
                try {
                    const msg = JSON.parse(raw.toString());
                    if (msg.act_id === 5 || msg.act_id === 390) {
                        this.ws.removeListener('message', handler);
                        responseReceived = true;
                        if (msg.code === 0) {
                            console.log('✅ 角色创建成功');
                            this.addTestResult('创建角色', true, '角色创建成功');
                            return setTimeout(resolve, 1500);
                        } else {
                            const errorMsg = msg.msg || '未知错误';
                            if ((errorMsg.includes('重复') || errorMsg.includes('已存在')) && retryCount < maxRetries) {
                                retryCount++;
                                const newName = `${CONFIG.testCharacter.name}_${Date.now()}`;
                                console.log(`🔄 角色名重复，尝试: ${newName}`);
                                return setTimeout(() => this.createCharacterWithName(newName, resolve), 800);
                            }
                            this.addTestResult('创建角色', false, errorMsg);
                            resolve();
                        }
                    }
                } catch (_) { }
            };

            this.ws.on('message', handler);
            this.createCharacterWithName(CONFIG.testCharacter.name, resolve);

            setTimeout(() => {
                if (!responseReceived) {
                    this.ws.removeListener('message', handler);
                    this.addTestResult('创建角色', false, '请求超时');
                    resolve();
                }
            }, 15000);
        });
    }

    createCharacterWithName(name, resolve) {
        const createData = {
            c: 5,
            d: { name, sex: CONFIG.testCharacter.sex, roleType: CONFIG.testCharacter.roleType, headIndex: CONFIG.testCharacter.headIndex }
        };
        console.log(`📤 发送创建角色请求:`, JSON.stringify(createData, null, 2));
        this.ws.send(JSON.stringify(createData));
    }

    async testSelectCharacter() {
        console.log('\n🎯 步骤5: 选择角色...');
        if (this.characters.length === 0) {
            this.addTestResult('选择角色', false, '没有可用角色');
            return;
        }
        return new Promise((resolve) => {
            const target = this.characters[0];
            const handler = (raw) => {
                try {
                    const msg = JSON.parse(raw.toString());
                    if (msg.act_id === 4) {
                        this.ws.removeListener('message', handler);
                        if (msg.code === 0) {
                            this.selectedCharacter = target;
                            console.log(`✅ 角色选择成功: ${target.name} (ID: ${target.id})`);
                            this.addTestResult('选择角色', true, `选择角色: ${target.name}`);
                            return setTimeout(resolve, 1200);
                        }
                        this.addTestResult('选择角色', false, msg.msg || '选择失败');
                        resolve();
                    }
                } catch (_) { }
            };
            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 4, d: { characterId: target.id } }));
            setTimeout(() => {
                this.ws.removeListener('message', handler);
                this.addTestResult('选择角色', false, '请求超时');
                resolve();
            }, 10000);
        });
    }

    async testCode1006GetResistances() {
        console.log('\n🛡️ 步骤6: 调用1006获取聚合抗性...');
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            this.addTestResult('1006接口测试(获取抗性)', false, 'WebSocket未连接');
            return;
        }
        return new Promise((resolve) => {
            let got = false;
            const handler = (raw) => {
                try {
                    const msg = JSON.parse(raw.toString());
                    if (msg.act_id === 1006) {
                        this.ws.removeListener('message', handler);
                        got = true;
                        if (msg.code === 0) {
                            console.log('✅ 1006接口返回成功');
                            this.resistances = msg.data || null;
                            this.addTestResult('1006接口测试(获取抗性)', true, '返回成功');
                        } else {
                            console.log(`❌ 1006接口失败: ${msg.msg || '未知错误'}`);
                            this.addTestResult('1006接口测试(获取抗性)', false, msg.msg || '调用失败');
                        }
                        resolve();
                    }
                } catch (_) { }
            };
            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 1006, d: {} }));
            setTimeout(() => {
                if (!got) {
                    this.ws.removeListener('message', handler);
                    this.addTestResult('1006接口测试(获取抗性)', false, '请求超时');
                    resolve();
                }
            }, 10000);
        });
    }

    async validateResistances() {
        console.log('\n🔍 步骤7: 验证抗性数据结构...');
        const r = this.resistances;
        if (!r || typeof r !== 'object') {
            this.addTestResult('抗性结构校验', false, '无数据或类型错误');
            return;
        }
        const expectedKeys = [
            'k_wl', 'k_wei', 'k_feng', 'k_fa', 'k_du', 'k_xi', 'k_luan', 'k_yao', 'k_ll',
            'r_bj', 'r_fj', 'r_fz', 'r_hb', 'r_mf', 'r_mz', 'r_zm'
        ];
        let ok = true;
        for (const key of expectedKeys) {
            if (!(key in r)) { ok = false; console.error(`❌ 缺少键: ${key}`); }
            else if (typeof r[key] !== 'number') { ok = false; console.error(`❌ 键 ${key} 的值不是数字`); }
        }
        if (ok) {
            this.addTestResult('抗性结构校验', true, '所有预期键存在且为数字');
            console.log('✅ 抗性结构校验通过');
        } else {
            this.addTestResult('抗性结构校验', false, '数据结构不符合预期');
        }
    }

    async testDisconnect() {
        console.log('\n🔌 步骤8: 断开WebSocket连接...');
        if (this.ws) { this.ws.close(); }
        this.addTestResult('断开连接', true, '连接已断开');
    }

    addTestResult(testName, success, message) {
        this.testResults.push({ test: testName, success, message, timestamp: new Date().toISOString() });
    }

    printTestResults() {
        console.log('\n📊 测试结果汇总:');
        console.log('='.repeat(50));
        let successCount = 0;
        let totalCount = this.testResults.length;
        this.testResults.forEach((result, index) => {
            const status = result.success ? '✅' : '❌';
            console.log(`${index + 1}. ${status} ${result.test}: ${result.message}`);
            if (result.success) successCount++;
        });
        console.log('='.repeat(50));
        console.log(`总计: ${successCount}/${totalCount} 项测试通过`);
        if (successCount === totalCount) console.log('🎉 所有测试通过！');
        else console.log('⚠️  部分测试失败，请检查日志');
    }

    async makeHttpRequest(path, method = 'GET', data = null) {
        return new Promise((resolve, reject) => {
            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path: path,
                method: method,
                headers: { 'Content-Type': 'application/json' }
            };
            if (data) {
                const postData = JSON.stringify(data);
                options.headers['Content-Length'] = Buffer.byteLength(postData);
            }
            const req = http.request(options, (res) => {
                let body = '';
                res.on('data', (chunk) => { body += chunk; });
                res.on('end', () => {
                    try {
                        const responseData = JSON.parse(body);
                        if (res.statusCode >= 200 && res.statusCode < 300) resolve(responseData);
                        else reject(new Error(`HTTP ${res.statusCode}: ${responseData.message || body}`));
                    } catch (error) {
                        if (res.statusCode >= 200 && res.statusCode < 300) resolve(body);
                        else reject(new Error(`HTTP ${res.statusCode}: ${body}`));
                    }
                });
            });
            req.on('error', (error) => reject(error));
            if (data) req.write(JSON.stringify(data));
            req.end();
        });
    }

    async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
}

async function main() {
    const tester = new Code1006Tester();
    await tester.runTest();
}

if (require.main === module) {
    main().catch((error) => {
        console.error('💥 测试脚本执行失败:', error.message);
        process.exit(1);
    });
}

module.exports = Code1006Tester;



